﻿using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OMC.DataManagement;
using Outlook = Microsoft.Office.Interop.Outlook;
using Manager = OMC.DataManagement.Manager;
using OMC.Classification;
using weka.classifiers.bayes;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Reflection;

namespace OutlookMailClassifier.Tests
{
    [TestClass]
    public class LokayMTest
    {
        Helper helper = new Helper();
        private List<Folder> folderList = new List<Folder>();

        [TestMethod]
        [DeploymentItem(@"lokay-m.pst")]
        public void AddUnaddPst()
        {
            helper.LoadPstByPath(@"lokay-m.pst");
            helper.UnloadPstByPath(@"lokay-m.pst");
        }

        /// <summary>
        /// Iterate over every mail in every folder. Check if it gets classified into the folder where it actually lies. Maybe a bit surprisingly some mails do not pass this test.
        /// </summary>
        [TestMethod]
        [DeploymentItem(@"lokay-m.pst")]
        public void SortIntoOwnFolder()
        {
            int count = 0;
            int countCorrect = 0;

            helper.LoadPstByPath(@"lokay-m.pst");

            Outlook.Explorer explorer = helper.GetApplicationObject().Explorers.Application.ActiveExplorer();
            Outlook.Stores stores = explorer.Session.Stores;
            Outlook.NameSpace nameSpace = explorer.Application.GetNamespace("MAPI");
            
            Manager manager = new Manager(stores, nameSpace, true);

            foreach (Outlook.Store store in stores)
            {
                if (store.DisplayName == "lokay-m")
                {
                    Outlook.Folder rootFolder = store.GetRootFolder() as Outlook.Folder;
                    manager.IndexFolder(rootFolder, folderList); //generates folder list
                    break;
                }
            }

            TextClassifierBuilder textClassifierBuilder = new TextClassifierBuilder();
            textClassifierBuilder.SetClassifier(new NaiveBayesMultinomialUpdateable());
            textClassifierBuilder.SetClasses(from fl in folderList select fl.EntryID + " " + fl.StoreID);
            foreach (Folder folder in folderList)
            {
                foreach (IClassifiable classifiable in folder)
                {
                    textClassifierBuilder.AddTrainingInstance(classifiable.GetContent(), folder.EntryID + " " + folder.StoreID, 1);
                }
            }
            textClassifierBuilder.FilterInstances();

            TextClassifier textClassifier = textClassifierBuilder.BuildClassifier();
            foreach (Folder folder in folderList)
            {
                foreach (IClassifiable classifiable in folder)
                {
                    count++;
                    string @class = textClassifier.Classify(classifiable.GetContent()).OrderByDescending(i => i.Probability).Take(1).ElementAt(0).Class;
                    if (@class == folder.EntryID + " " + folder.StoreID)
                    {
                        countCorrect++;
                    }
                }
            }

            helper.UnloadPstByPath(@"lokay-m.pst");

            //MessageBox.Show("countCorrect = " + countCorrect + "  count = " + count, "Info", MessageBoxButtons.OK, MessageBoxIcon.None);
            
            float threshold = 2223 / 2489; // 0.893 is an specifically for the lokay-m data set determined empirical value
            Assert.IsTrue((float)countCorrect / count >= threshold, "Too many items classified to folders other than the containing one. Expected: " + threshold + ", but got " + (float)countCorrect/count);
        }

        /// <summary>
        /// Iterate over every mail in every folder. Remove it from its original folder and check if gets classified to the same folder, then revert.
        /// </summary>
        [TestMethod]
        [DeploymentItem(@"lokay-m.pst")]
        public void SortIntoOtherFolder()
        {
            int count = 0;
            int countCorrect = 0;

            helper.LoadPstByPath(@"lokay-m.pst");

            Outlook.Explorer explorer = helper.GetApplicationObject().Explorers.Application.ActiveExplorer();
            Outlook.Stores stores = explorer.Session.Stores;
            Outlook.NameSpace nameSpace = explorer.Application.GetNamespace("MAPI");

            Manager manager = new Manager(stores, nameSpace, true);

            foreach (Outlook.Store store in stores)
            {
                if (store.DisplayName == "lokay-m")
                {
                    Outlook.Folder rootFolder = store.GetRootFolder() as Outlook.Folder;
                    manager.IndexFolder(rootFolder, folderList); //generates folder list
                    break;
                }
            }

            TextClassifierBuilder textClassifierBuilder = new TextClassifierBuilder();
            textClassifierBuilder.SetClassifier(new NaiveBayesMultinomialUpdateable());
            textClassifierBuilder.SetClasses(from fl in folderList select fl.EntryID + " " + fl.StoreID);
            foreach (Folder folder in folderList)
            {
                foreach (IClassifiable classifiable in folder)
                {
                    textClassifierBuilder.AddTrainingInstance(classifiable.GetContent(), folder.EntryID + " " + folder.StoreID, 1);
                }
            }
            textClassifierBuilder.FilterInstances();

            TextClassifier textClassifier = textClassifierBuilder.BuildClassifier();
            foreach (Folder folder in folderList)
            {
                foreach (IClassifiable mailContent in folder)
                {
                    count++;

                    //Outlook.MailItem mail = classifiable as Outlook.MailItem;
                    //MailContent mailContent = new MailContent(mail.Body, mail.Subject, mail.SenderEmailAddress, mail.To);

                    // unadd
                    textClassifierBuilder.AddTrainingInstance(mailContent.GetContent(), folder.EntryID + " " + folder.StoreID, -1);
                    textClassifier.updateClassifier(textClassifierBuilder.Text2FilteredInstance(mailContent.GetContent(), folder.EntryID + " " + folder.StoreID, -1));

                    string @class = textClassifier.Classify(mailContent.GetContent()).OrderByDescending(i => i.Probability).Take(1).ElementAt(0).Class;
                    if (@class == folder.EntryID + " " + folder.StoreID)
                    {
                        countCorrect++;
                    }

                    // add
                    textClassifierBuilder.AddTrainingInstance(mailContent.GetContent(), folder.EntryID + " " + folder.StoreID, 1);
                    textClassifier.updateClassifier(textClassifierBuilder.Text2FilteredInstance(mailContent.GetContent(), folder.EntryID + " " + folder.StoreID, 1));
                }
            }

            helper.UnloadPstByPath(@"lokay-m.pst");

            //MessageBox.Show("countCorrect = " + countCorrect + "  count = " + count, "Info", MessageBoxButtons.OK, MessageBoxIcon.None);

            float threshold = 2105 / 2489; // 0.846 is an specifically for the lokay-m data set determined empirical value
            Assert.IsTrue((float)countCorrect / count >= threshold, "Too many items classified to wrong folders. Expected: " + threshold + ", but got " + (float)countCorrect/count);
        }
    }
}
